package com.searchtree.binarysearchtree;

import com.searchtree.main.Utilities;
import com.searchtree.tree.AbstractNode;
import com.searchtree.tree.LeafNode;
import com.searchtree.tree.AbstractTree;

public class BinarySearchTree extends AbstractTree 
{
	private static BinarySearchTree binaryTree;
	private BinarySearchTreeNode rootNode;

	private BinarySearchTree() 
	{
		super();
	}

	public static BinarySearchTree getInstance() 
	{
		if (binaryTree == null) 
		{
			binaryTree = new BinarySearchTree();
		}
		
		return binaryTree;
	}
	
	public void addNode(String key) 
	{
		if (rootNode == null) 
		{		
			rootNode = new BinarySearchTreeNode(key);
		} 
		else 
		{
			AbstractNode n = rootNode;
			while (!(n instanceof LeafNode)) 
			{
				BinarySearchTreeNode tempNode = (BinarySearchTreeNode) n;
				int decide = Utilities.compareStringValues(tempNode.getKey(),key);
				if (decide == -1) 
				{
					if (tempNode.getRightNode() instanceof LeafNode) 
					{
						tempNode.setRightNode(new BinarySearchTreeNode(key));
						break;
					}
					n = tempNode.getRightNode();
				} 
				else if (decide == 1) 
				{
					if (tempNode.getLeftNode() instanceof LeafNode)
					{
						tempNode.setLeftNode(new BinarySearchTreeNode(key));
						break;
					}
					n = tempNode.getLeftNode();
				} 
				else 
				{
					break;
				}
			}
		}
	}

	@Override
	public AbstractNode searchNode(String key) 
	{
		return searchNode(key, this.rootNode);
	}

	@Override
	public AbstractNode searchNode(String key, AbstractNode n) 
	{
		if (n instanceof LeafNode) 
		{
			return n;
		} 
		else 
		{
			BinarySearchTreeNode tempNode = (BinarySearchTreeNode) n;
			int decide = Utilities.compareStringValues(tempNode.getKey(), key);
			if (decide == 1) 
			{
				return this.searchNode(key, tempNode.getLeftNode());
			} 
			else if (decide == -1) 
			{
				return this.searchNode(key, tempNode.getRightNode());
			} 
			else 
			{
				return n;
			}
		}
	}
	
	public String searchKey(String key) 
	{
		AbstractNode n = searchNode(key);
		if (n instanceof LeafNode) 
		{
			return "The searchterm: " + key + "can not be found in this binaryTree";
		}
		else 
		{
			BinarySearchTreeNode bsn = (BinarySearchTreeNode)(n);
			
			return bsn.toString();
		}
	}

	public BinarySearchTreeNode getRootNode() 
	{
		return rootNode;
	}
}